const M3U8 = require("m3u8-parser")
var parser = new M3U8.Parser();
const fs = require("fs");
const path = require("path");
const axios = require("axios").default;
const url = require("url");
const runPara = require("run-parallel-limit");

fs.readFile(path.join(__dirname, "./1.m3u8"), async (err, data) => {
  parser.push(data.toString());
  /**@type {string[]} */
  let downloadUris = parser.manifest.segments.map(e => `https://dtliving-pre.alicdn.com/live_hp/${e.uri}`);
  debugger
  let o_download = await promiseAll(downloadUris.map(link => {
    return function () {
      return download(link);
    }
  }));

  debugger
  await createFileList(o_download.map(e => e.dic_path)
    // .sort((a, b) => a.localeCompare(b))
  );
  debugger
});


/**
 * @returns {Promise<{dic_path:String}>}
 * @param {String} uri__ 
 */
function download(uri__) {
  let parsed = url.parse(uri__);
  let basename = path.basename(parsed.pathname);
  bname = `part_${basename}`
  // debugger
  // let bname = path.posix.basename(parsed.path)
  return new Promise(resolve => {
    axios.get(uri__, {
      responseType: "stream"
    }).then(s => {

      let local_f = path.join(__dirname, bname);
      let writeStream = fs.createWriteStream(local_f);
      s.data.pipe(writeStream);
      writeStream.on("close", () => {
        return resolve({ dic_path: local_f });
      });
      writeStream.on("error", (err) => {
        debugger
      })
    }).catch(async axerr => {
      debugger
      console.log(axerr, uri__, axerr.message, axerr);
      let o_retry = await download(uri__);
      resolve(o_retry);
    })
  })
}

/**
 * 
 * @param {String[]} local_files 
 */
function createFileList(local_files) {
  return new Promise(resolve => {
    fs.writeFile(path.join(__dirname, "filelist.txt"), local_files.map(e => `file '${path.basename(e)}'`).join("\n"), (err) => {
      resolve();
    })
  })
}

/**
 * 
 * @param {Function<>[]} promise_gen_functions
 * @param {Number} parallel_limit 
 */
function promiseAll(promise_gen_functions, parallel_limit = 1) {
  return new Promise(resolve => {
    let results = [];
    let tasks = promise_gen_functions.map(func => async cb => {
      let o_do = await func();
      results.push(o_do);
      cb();
    });
    runPara(tasks, parallel_limit, () => {
      results
      debugger
      return resolve(results);
    })
  })
}